package com.yixun.qfbao.api.service.impl;

import com.yixun.qfbao.api.service.ReportRelationService;
import com.yixun.qfbao.apidto.ReportDto;
import com.yixun.qfbao.apidto.ReportOverdueConfigDto;
import com.yixun.qfbao.apidto.ReportPremisesDto;
import com.yixun.qfbao.apidto.ReportRelationResDto;
import com.yixun.qfbao.dao.ApiLogDao;
import com.yixun.qfbao.dao.DepartmentDao;
import com.yixun.qfbao.model.*;
import com.yixun.qfbao.model.dto.*;
import com.yixun.qfbao.model.enums.DecisionApplyEnum;
import com.yixun.qfbao.model.enums.DecisionResetEnum;
import com.yixun.qfbao.model.enums.DecisionTypeEnum;
import com.yixun.qfbao.model.enums.TimeUnitTypeEnum;
import com.yixun.qfbao.service.CompanyService;
import com.yixun.qfbao.service.OverdueConfigService;
import com.yixun.qfbao.service.PartnerInfoService;
import com.yixun.qfbao.service.ReportExternalService;
import com.yixun.qfbao.util.DateUtils;
import com.yixun.qfbao.xf.model.CaseMember;
import com.yixun.qfbao.xf.model.CustomerPremises;
import com.yixun.qfbao.xf.model.FollowUpList;
import com.yixun.qfbao.xf.model.Premises;
import com.yixun.qfbao.xf.model.dto.CaseMemberDto;
import com.yixun.qfbao.xf.model.dto.CustomerPremisesDto;
import com.yixun.qfbao.xf.model.dto.FollowUpListDto;
import com.yixun.qfbao.xf.service.CaseMemberService;
import com.yixun.qfbao.xf.service.CustomerPremisesService;
import com.yixun.qfbao.xf.service.FollowUpListService;
import com.yixun.qfbao.xf.service.PremisesService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ReportRelationServiceImpl implements ReportRelationService {

    @Autowired
    CustomerPremisesService customerPremisesService;
    @Autowired
    PremisesService premisesService;
    @Autowired
    CompanyService companyService;
    @Autowired
    PartnerInfoService partnerInfoService;
    @Autowired
    DepartmentDao departmentDao;
    @Autowired
    FollowUpListService followUpListService;
    @Autowired
    OverdueConfigService overdueConfigService;
    @Autowired
    CaseMemberService caseMemberService;
    @Autowired
    ReportExternalService reportExternalService;
    @Autowired
    ApiLogDao apiLogDao;

    @Override
    public ReportRelationResDto getReportRelation(Long reportId) {
        ReportRelationResDto resDto = new ReportRelationResDto();
        CustomerPremises customerPremises = customerPremisesService.selectById(reportId);
        if(Objects.isNull(customerPremises)){
            return resDto;
        }
        Long premisesId = customerPremises.getPremisesId();
        String mobile = customerPremises.getMobile();

        Premises premises = premisesService.selectSimpleById(premisesId);
        if(Objects.isNull(premises)){
            return resDto;
        }
        ReportPremisesDto reportPremisesDto = new ReportPremisesDto();
        BeanUtils.copyProperties(premises, reportPremisesDto);

        // 楼盘规则
        OverdueConfigDto overdueConfigDto = new OverdueConfigDto();
        overdueConfigDto.setPremisesId(premises.getId());
        List<OverdueConfig> overdueConfigList = overdueConfigService.selectListByDto(overdueConfigDto);
        List<ReportOverdueConfigDto> premisesConfig = buildReportOverdueConfig(overdueConfigList);

        // 楼盘驻场
        CaseMemberDto caseMemberDto = new CaseMemberDto();
        caseMemberDto.setPremisesId(premises.getId());
        List<CaseMember> caseMemberList = caseMemberService.selectListByDto(caseMemberDto);

        CustomerPremisesDto customerPremisesDto = new CustomerPremisesDto();
        customerPremisesDto.setPremisesId(premisesId);
        customerPremisesDto.setMobile(mobile);
        List<CustomerPremises> customerPremisesList = customerPremisesService.selectListByDto(customerPremisesDto);
        if(CollectionUtils.isEmpty(customerPremisesList)){
            return resDto;
        }
        // 同楼盘+手机号报备记录
        List<ReportDto> reportList = buildReportList(premises, customerPremisesList);

        // 外部报备逻辑
        ReportExternalDto reportExternalDto = new ReportExternalDto();
        reportExternalDto.setReportId(reportId);
        ReportExternal reportExternal = reportExternalService.selectByDto(reportExternalDto);

        String reportUuid = "";
        if(Objects.nonNull(reportExternal)){
            Date createTime = customerPremises.getCreateTime();
            Date createTimeBefore = DateUtils.addHour(createTime, -1);
            Date createTimeAfter = DateUtils.addHour(createTime, 1);

            reportUuid = reportExternal.getReportUuid();
            ApiLogDto apiLogDto = new ApiLogDto();
            apiLogDto.setRequestContent(reportUuid);
            apiLogDto.setCreateTimeBefore(createTimeBefore);
            apiLogDto.setCreateTimeAfter(createTimeAfter);
            List<ApiLog> apiLogList = apiLogDao.selectListByDto(apiLogDto);
            resDto.setApiLogList(apiLogList);
        }

        resDto.setReportPremises(reportPremisesDto);
        resDto.setReportList(reportList);
        resDto.setPremisesConfig(premisesConfig);
        resDto.setCaseMemberList(caseMemberList);
        return resDto;
    }

    private List<ReportDto> buildReportList(Premises premises, List<CustomerPremises> customerPremisesList){
        List<ReportDto> reportList = new ArrayList<>();
        // 报备涉及公司: 所属公司及经纪人公司
        // 报备涉及的用户: 报备人及代报备人
        List<Long> reportIds = new ArrayList<>();
        List<Long> companyIds = new ArrayList<>();
        List<Long> partnerIds = new ArrayList<>();
        List<Long> deptIds = new ArrayList<>();
        for(CustomerPremises cp: customerPremisesList){
            reportIds.add(cp.getId());
            companyIds.add(cp.getStaffCompanyId());
            companyIds.add(cp.getCompanyId());
            if(Objects.nonNull(cp.getPartnerId())){
                partnerIds.add(cp.getPartnerId());
            }
            partnerIds.add(cp.getStaffId());
        }
        // 公司信息
        Map<Long, CompanyDto> companyDtoMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(companyIds)){
            CompanyDto companyDto = new CompanyDto();
            companyDto.setIds(companyIds);
            List<CompanyDto> companyDtoList = companyService.selectListByIds(companyDto);
            companyDtoMap = companyDtoList.stream()
                    .collect(Collectors.toMap(CompanyDto::getId, Function.identity()));
        }

        // 用户信息
        Map<Long, PartnerInfo> partnerInfoMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(companyIds)){
            PartnerInfoDto partnerInfoDto = new PartnerInfoDto();
            partnerInfoDto.setIds(partnerIds);
            List<PartnerInfo> partnerInfoList = partnerInfoService.selectListByDto(partnerInfoDto);
            partnerInfoMap = partnerInfoList.stream()
                    .collect(Collectors.toMap(PartnerInfo::getId, Function.identity()));
            deptIds = partnerInfoList.stream()
                    .map(PartnerInfo::getDeptId)
                    .collect(Collectors.toList());
        }

        // 用户部门信息
        Map<Long, Department> departmentMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(deptIds)){
            DepartmentDto departmentDto = new DepartmentDto();
            departmentDto.setDeptIds(deptIds);
            List<Department> departmentList = departmentDao.selectAllListByDto(departmentDto);
            departmentMap = departmentList.stream()
                    .collect(Collectors.toMap(Department::getId, Function.identity()));
        }

        // 跟进记录
        FollowUpListDto followUpListDto = new FollowUpListDto();
        followUpListDto.setCusPreIds(reportIds);
        List<FollowUpList> followList = followUpListService.selectListByIds(followUpListDto);

        for(CustomerPremises cp: customerPremisesList){
            ReportDto reportDto = new ReportDto();
            reportDto.setId(cp.getId());
            reportDto.setPremisesId(cp.getPremisesId());
            reportDto.setPremisesName(premises.getName());
            reportDto.setName(cp.getName());
            reportDto.setMobile(cp.getMobile());
            CompanyDto companyDto = companyDtoMap.get(cp.getStaffCompanyId());
            reportDto.setStaffCompanyId(cp.getStaffCompanyId());
            reportDto.setStaffCompanyName(companyDto.getCompanyName());
            PartnerInfo partnerInfo = partnerInfoMap.get(cp.getStaffId());
            reportDto.setStaffId(cp.getStaffId());
            reportDto.setStaffName(partnerInfo.getAccountName());
            reportDto.setStaffPhone(partnerInfo.getPhone());
            Department department = departmentMap.get(partnerInfo.getDeptId());
            reportDto.setDepartmentName(department.getDepartmentName());
            reportDto.setLayer(department.getLayer());
            companyDto = companyDtoMap.get(cp.getCompanyId());
            reportDto.setCompanyId(cp.getCompanyId());
            reportDto.setCompanyName(companyDto.getCompanyName());
            reportDto.setPartnerId(cp.getPartnerId());
            reportDto.setReportPhone(cp.getReportPhone());
            reportDto.setReportType(cp.getReportType());
            reportDto.setCreateTime(cp.getCreateTime());
            reportDto.setReportPeriodTime(cp.getReportPeriodTime());
            reportDto.setReportValidTime(cp.getReportValidTime());
            reportDto.setLookPeriodTime(cp.getLookPeriodTime());
            reportDto.setHopeVisitTime(cp.getHopeVisitTime());
            reportDto.setVisitProtectTime(cp.getVisitProtectTime());
            reportDto.setVisitBaohuTime(cp.getVisitBaohuTime());
            reportDto.setVisitPastTime(cp.getVisitPastTime());
            reportDto.setVisitTime(cp.getVisitTime());
            reportDto.setPayDepositTime(cp.getPayDepositTime());
            reportDto.setSubscribeTime(cp.getSubscribeTime());
            reportDto.setSignTime(cp.getSignTime());
            reportDto.setDealFailTime(cp.getDealFailTime());
            reportDto.setUpdateTime(cp.getUpdateTime());
            reportDto.setVisitState(cp.getVisitState());
            reportDto.setCustomerStatus(cp.getCustomerStatus());
            reportDto.setConfirmStatus(cp.getConfirmStatus());
            reportDto.setRemark(cp.getRemark());

            List<FollowUpList> filterFollowList = followList.stream()
                    .filter(item -> item.getCustomerPremisesId().equals(cp.getId()))
                    .collect(Collectors.toList());
            reportDto.setFollowUpLists(filterFollowList);

            reportList.add(reportDto);
        }
        return reportList;
    }

    private List<ReportOverdueConfigDto> buildReportOverdueConfig(List<OverdueConfig> overdueConfigList){
        List<ReportOverdueConfigDto> reportOverdueConfigDtoList = new ArrayList<>();

        for(OverdueConfig overdueConfig: overdueConfigList){
            ReportOverdueConfigDto reportOverdueConfigDto = new ReportOverdueConfigDto();
            BeanUtils.copyProperties(overdueConfig, reportOverdueConfigDto);
            if(Objects.nonNull(overdueConfig.getDecisionApply())){
                String decisionApplyName = DecisionApplyEnum.getDescByNo(overdueConfig.getDecisionApply());
                reportOverdueConfigDto.setDecisionApplyName(decisionApplyName);
            }
            if(Objects.nonNull(overdueConfig.getDecisionTimeType())){
                String decisionTimeTypeName = TimeUnitTypeEnum.getDescByNo(String.valueOf(overdueConfig.getDecisionTimeType()));
                reportOverdueConfigDto.setDecisionTimeTypeName(decisionTimeTypeName);
            }

            if(Objects.nonNull(overdueConfig.getDecisionType())){
                String decisionTypeName = DecisionTypeEnum.getDescByNo(overdueConfig.getDecisionType());
                reportOverdueConfigDto.setDecisionTypeName(decisionTypeName);
            }
            if(Objects.nonNull(overdueConfig.getDecisionService())){
                String decisionServiceName = DecisionServiceEnum.getDescByNo(overdueConfig.getDecisionService());
                reportOverdueConfigDto.setDecisionTypeName(decisionServiceName);
            }
            if(Objects.nonNull(overdueConfig.getDecisionReset())){
                String decisionResetName = DecisionResetEnum.getDescByNo(overdueConfig.getDecisionReset());
                reportOverdueConfigDto.setDecisionTypeName(decisionResetName);
            }
            reportOverdueConfigDtoList.add(reportOverdueConfigDto);
        }
        return reportOverdueConfigDtoList;
    }

}
